perm filename EFSEND.C[11,HE] blob
sn#688190 filedate 1982-12-06 generic text, type T, neo UTF8
/* LINTLIBRARY */
/*
* efsendend.c
*
* EFTP Package
*
* EfSendEnd -- terminate (normally) an EFTP transfer.
*
* Jeffrey Mogul @ Stanford 28-January-1981
*/
#include <eftp.h>
#include <pupconstants.h>
#include <pupstatus.h>
EfSendEnd(Efchan)
struct EftpChan *Efchan; /* channel on which to end transfer */
{ /* */
char dummy; /* instead of a send buffer */
int retry;
int inhibit; /* INVARIANT -- MUST BE 0 or 1 */
int rstat;
uchar rpuptype;
ulong rpupid;
char msgbuf[100];
int msgbuflen;
inhibit = 0; /* don't inhibit packet sending */
for (retry=0; retry < Efchan->WaitTime ; retry++) {
/* attempt to get a packet accross */
/* the "inhibit" flag is used to avoid re-sending too
* quickly if we get a duplicate ACK; the problem is
* that an ACK for the packet we just sent may already
* be on its way, and we will get into a situation where
* every packet is sent twice if we don't watch it.
*/
if (!inhibit) /* test, (and clear later) inhibit */
pupwrite(&Efchan->pchan,EFTPEND,Efchan->sequence,
&dummy,0);
/* pup id is sequence number */
inhibit = 0;
/* wait for an ACK */
rstat = pupread(&Efchan->pchan,msgbuf,&msgbuflen,
&rpuptype, &rpupid, NULL, NULL);
if (rstat == BADCKSUM || rstat == TIMEOUT) continue;
/* got a packet */
switch ((int)rpuptype) {
case EFTPACK:
if (rpupid == Efchan->sequence) { /* right ack */
Efchan->sequence++; /* incr. sequence */
/* now, launch second END to tell receiver
* to finish its dally.
*/
pupwrite(&Efchan->pchan,EFTPEND,
Efchan->sequence,&dummy,0);
return(OK);
}
else { /* got the wrong ack */
if (rpupid > Efchan->sequence) {
/* future packet acked ?! */
return(EFTP_BADACK);
}
}
/* other possibility is repeated ack; ignore it,
* but inhibit resending the packet for next
* timeout period - another ack may be coming.
*/
inhibit++;
break; /* effect is to repeat loop & retry */
case EFTPABORT:
EftpAbortCode = *(ushort *)msgbuf;
movestring(&msgbuf[2],EftpErrMsg,msgbuflen-2);
EftpErrMsg[msgbuflen-2] = 0; /* nullterm it */
return(EFTP_ABORT);
default: /* we got the wrong packet type! */
return(EFTP_ERROR);
}
}
/* too many retries */
return(TIMEOUT);
}